# -*- coding: utf-8 -*-
from kivy.config import ConfigParser

import constants
from model.gamestate import GameTypes
from model.dictionaryinfo import DictionaryInfo
from model.dictionary import Dictionary
from constants import FAILED_SOUND, GUESSED_SOUND, \
    PUT_BACK_SOUND, \
    MAX_PLAYERS, MIN_PLAYERS,\
    MAX_TIME, MIN_TIME, MAX_WORDS, MIN_WORDS,\
    CONFIG_FILE, HOST


class SysSettings(object):
    def __init__(self, config_file):
        if config_file is None or config_file is '':
            raise Exception('SysSettings: no config file specified')

        self.config_file = config_file
        self.set_conf_ver()
        self.load_config()

    def set_conf_ver(self):
        with open(CONFIG_FILE, 'r') as config:
                conf_ver = config.readline()
        self.conf_ver = conf_ver

    def _load_game_options(self):
        section = 'Game'
        countdown_time_sec =\
            self.config.getdefault(section, 'countdown_time_sec', '3')
        skip_words =\
            self.config.getdefault(section, 'skip_words', '0')
        is_progress_bar =\
            self.config.getdefault(section, 'is_progress_bar', '1')
        may_delete_player =\
            self.config.getdefault(section, 'may_delete_player', '1')
        may_skip_turn =\
            self.config.getdefault(section, 'may_skip_turn', '1')
        may_pause_game =\
            self.config.getdefault(section, 'may_pause_game', '1')
        may_replay_round =\
            self.config.getdefault(section, 'may_replay_round', '1')
        send_statistics =\
            self.config.getdefault(section, 'send_statistics', '1')
        server_name =\
            self.config.getdefault(section, 'server_name', HOST)
        confifmation_time_sec =\
            self.config.getdefault(section, 'confirmation_time_sec', '1')
        show_tournament_buttons =\
            self.config.getdefault(section, 'show_tournament_buttons', '0')

        self.game = Game(countdown_time_sec, skip_words, is_progress_bar,
                         may_delete_player, may_skip_turn, may_pause_game,
                         may_replay_round, send_statistics, server_name,
                         confifmation_time_sec, show_tournament_buttons)

    def _load_graphics_options(self):
        section = 'Graphics'
        horizontal_orientation =\
            self.config.getdefault(section, 'horizontal_orientation', '270')
        vertical_orientation =\
            self.config.getdefault(section, 'vertical_orientation', '0')

        self.graphics = Graphics(horizontal_orientation, vertical_orientation)

    def _load_sound_options(self):
        section = 'Sound'
        sound_on =\
            self.config.getdefault(section, 'sound_on', '1')
        sound_guessed =\
            self.config.getdefault(section, 'sound_guessed', GUESSED_SOUND)
        sound_failed =\
            self.config.getdefault(section, 'sound_failed', FAILED_SOUND)
        sound_put_back =\
            self.config.getdefault(section, 'sound_put_back', PUT_BACK_SOUND)

        self.sound = Sound(sound_on, sound_guessed,
                           sound_failed, sound_put_back)

    def _load_quick_game_defaults_options(self):
        section = 'Quick Game Defaults'
        def_qg_players =\
            self.config.getdefault(section, 'def_players', '6')
        def_qg_time_sec =\
            self.config.getdefault(section, 'def_time_sec', '20')
        def_qg_words_per_player =\
            self.config.getdefault(section, 'def_words_per_player', '10')

        self.quick_game = QuickGame(def_qg_players, def_qg_time_sec,
                                    def_qg_words_per_player)

    def _load_dictionaries_options(self):
        section = 'Dictionaries Defaults'
        dicts_list = DictionaryInfo.parse_dictionaries_metadata()
        for cur_dict in dicts_list:
            val = self.config.getdefault(
                section, cur_dict.file_name, cur_dict.enable_by_default)
            cur_dict.enable_by_default = (val == '1' or val is True)
        self.dictionaries = Dictionaries(dicts_list)

    def _load_next_round_options(self):
        section = 'Next Round'
        game_type =\
            self.config.getdefault(section, 'game_type',
                                   str(GameTypes.HAT_STANDARD))
        keep_failed_words =\
            self.config.getdefault(section, 'keep_failed_words', '0')
        self.next_round = NextRound(game_type, keep_failed_words)

    def load_config(self):
        self.config = ConfigParser()
        self.config.read(self.config_file)

        self._load_game_options()
        self._load_graphics_options()
        self._load_sound_options()
        self._load_quick_game_defaults_options()
        self._load_dictionaries_options()
        self._load_next_round_options()

    def set_property(self, section, key, value):
        if section == 'Game':
            self.game.set_property(key, value)
        elif section == 'Graphics':
            self.graphics.set_property(key, value)
        elif section == 'Sound':
            self.sound.set_property(key, value)
        elif section == 'Quick Game Defaults':
            self.quick_game.set_property(key, value)
        elif section == 'Dictionaries Defaults':
            self.dictionaries.set_property(key, value)
        elif section == 'Next Round':
            self.next_round.set_property(key, value)

        # writing config version
        with open(CONFIG_FILE, 'r+') as file:
            lines = file.readlines()
            file.seek(0)
            file.writelines([self.conf_ver] + lines)


class ObservableSettings(object):
    def __init__(self):
        self.observers = []

    def add_observer(self, observer):
        self.observers.append(observer)

    def notify_observers(self):
        for observer in self.observers:
            observer(self)


class Game(ObservableSettings):
    def __init__(self, countdown_time_sec, skip_words, is_progress_bar,
                 may_delete_player, may_skip_turn, may_pause_game,
                 may_replay_round, send_statistics, server_name,
                 confirmation_time_sec, show_tournament_buttons):
        super(Game, self).__init__()
        self.set_property('countdown_time_sec', countdown_time_sec)
        self.set_property('skip_words', skip_words)
        self.set_property('is_progress_bar', is_progress_bar)
        self.set_property('may_delete_player', may_delete_player)
        self.set_property('may_skip_turn', may_skip_turn)
        self.set_property('may_pause_game', may_pause_game)
        self.set_property('may_replay_round', may_replay_round)
        self.set_property('send_statistics', send_statistics)
        self.set_property('server_name', server_name)
        self.set_property('confirmation_time_sec', confirmation_time_sec)
        self.set_property('show_tournament_buttons', show_tournament_buttons)

    def set_property(self, key, value):
        if key == 'countdown_time_sec':
            self.countdown_time_sec = int(value)
        elif key == 'skip_words':
            if value == 'Inf':
                self.skip_words = constants.INF
            else:
                self.skip_words = int(value)
        elif key == 'is_progress_bar':
            self.is_progress_bar = str(value) == '1'
        elif key == 'may_delete_player':
            self.may_delete_player = str(value) == '1'
        elif key == 'may_skip_turn':
            self.may_skip_turn = str(value) == '1'
        elif key == 'may_pause_game':
            self.may_pause_game = str(value) == '1'
        elif key == 'may_replay_round':
            self.may_replay_round = str(value) == '1'
        elif key == 'send_statistics':
            self.send_statistics = str(value) == '1'
        elif key == 'server_name':
            self.server_name = str(value)
        elif key == 'confirmation_time_sec':
                    self.confirmation_time_sec = str(value)
        elif key == 'show_tournament_buttons':
            self.show_tournament_buttons = str(value) == '1'
        self.notify_observers()


class Graphics(ObservableSettings):
    def __init__(self, horizontal_orientation, vertical_orientation):
        super(Graphics, self).__init__()
        self.set_property('horizontal_orientation', horizontal_orientation)
        self.set_property('vertical_orientation', vertical_orientation)

    def set_property(self, key, value):
        if key == 'horizontal_orientation':
            self.horizontal_orientation = int(value)
        elif key == 'vertical_orientation':
            self.vertical_orientation = int(value)
        self.notify_observers()


class Sound(ObservableSettings):
    def __init__(self, sound_on, sound_guessed, sound_failed,
                 sound_put_back):
        super(Sound, self).__init__()
        self.set_property('sound_on', sound_on)
        self.set_property('sound_guessed', sound_guessed)
        self.set_property('sound_failed', sound_failed)
        self.set_property('sound_put_back', sound_put_back)

    def set_property(self, key, value):
        if key == 'sound_on':
            self.sound_on = str(value) == '1'
        elif key == 'sound_guessed':
            self.sound_guessed = str(value)
        elif key == 'sound_failed':
            self.sound_failed = str(value)
        elif key == 'sound_put_back':
            self.sound_put_back = str(value)
        self.notify_observers()


class QuickGame(ObservableSettings):
    def __init__(self, def_players, def_time_sec, def_words_per_player):
        super(QuickGame, self).__init__()
        self.set_property('def_players', def_players)
        self.set_property('def_time_sec', def_time_sec)
        self.set_property('def_words_per_player', def_words_per_player)

    def set_properties(self, props={}):
        for key in props:
            value = props[key]
            self.set_property(key, value)
        self.notify_observers()

    def set_property(self, key, value):
        value = int(value)
        if key == 'def_players':
            if value > MAX_PLAYERS:
                value = MAX_PLAYERS
            elif value < MIN_PLAYERS:
                value = MIN_PLAYERS
            self.def_players = int(value)
        elif key == 'def_time_sec':
            if value > MAX_TIME:
                value = MAX_TIME
            elif value < MIN_TIME:
                value = MIN_TIME
            self.def_time_sec = int(value)
        elif key == 'def_words_per_player':
            if value > MAX_WORDS:
                value = MAX_WORDS
            elif value < MIN_WORDS:
                value = MIN_WORDS
            self.def_words_per_player = int(value)
        self.notify_observers()


class Dictionaries(ObservableSettings):
    enabled_dictionaries = {}

    def __init__(self, dicts_list):
        super(Dictionaries, self).__init__()
        for cur_dict in dicts_list:
            Dictionaries.enabled_dictionaries[cur_dict.file_name] =\
                cur_dict.enable_by_default
        DictionaryInfo.enabled_dictionaries = Dictionaries.enabled_dictionaries

    def set_property(self, key, value):
        if (value == '1' or value is True):
            Dictionaries.enabled_dictionaries[key] = True
        else:
            Dictionaries.enabled_dictionaries[key] = False
        Dictionary.invalidate()
        DictionaryInfo.enabled_dictionaries = Dictionaries.enabled_dictionaries
        self.notify_observers()


class NextRound(ObservableSettings):
    def __init__(self, game_type, keep_failed_words):
        super(NextRound, self).__init__()
        self.game_type = game_type
        self.keep_failed_words = int(keep_failed_words)

    def set_property(self, key, value):
        if key == 'game_type':
            self.game_type = value
        elif key == 'keep_failed_words':
            self.keep_failed_words = int(keep_failed_words)
        self.notify_observers()
